//package com.zxy.supplier_system.server.utils.wechat.pay
//
//import com.fasterxml.jackson.databind.JsonNode
//import com.fasterxml.jackson.databind.ObjectMapper
//import com.fasterxml.jackson.databind.node.ObjectNode
//import com.wechat.pay.contrib.apache.httpclient.WechatPayHttpClientBuilder
//import com.wechat.pay.contrib.apache.httpclient.auth.PrivateKeySigner
//import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Credentials
//import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Validator
//import com.wechat.pay.contrib.apache.httpclient.cert.CertificatesManager
//import com.wechat.pay.contrib.apache.httpclient.constant.WechatPayHttpHeaders
//import com.wechat.pay.contrib.apache.httpclient.notification.NotificationHandler
//import com.wechat.pay.contrib.apache.httpclient.notification.NotificationRequest
//import com.wechat.pay.contrib.apache.httpclient.util.PemUtil
//import com.zxy.supplier_system.server.configuration.WechatProperties
//import jakarta.servlet.http.HttpServletRequest
//import org.apache.commons.codec.binary.Base64
//import org.apache.commons.lang3.RandomStringUtils
//import org.apache.http.HttpHeaders
//import org.apache.http.HttpRequestInterceptor
//import org.apache.http.client.methods.HttpPost
//import org.apache.http.entity.StringEntity
//import org.springframework.beans.factory.annotation.Value
//import org.springframework.core.io.Resource
//import org.springframework.stereotype.Component
//import java.io.ByteArrayOutputStream
//import java.nio.charset.StandardCharsets
//import java.security.Signature
//import java.time.LocalDateTime
//import java.time.format.DateTimeFormatter
//import java.util.*
//import kotlin.reflect.KProperty
//
//
///**
// * Wechat pay v3 api
// * https://pay.weixin.qq.com/wiki/doc/apiv3/apis/index.shtml
// */
//@Component
//class WechatPayClient(
//    private val wechatProperties: WechatProperties,
//    @Value("classpath:wechat/pay/apiclient_key.pem") resource: Resource,
//) {
//
//    companion object {
//        private val log by LoggerDelegate()
//    }
//
//    private val apiV3KeyByteArray = wechatProperties.pay.apiV3Key.toByteArray(
//        StandardCharsets.UTF_8
//    )
//
//    private val objectMapper = ObjectMapper()
//    private val privateKey = PemUtil.loadPrivateKey(resource.inputStream)
//    private val merchantId = wechatProperties.pay.merchantId
//    private val verifier = CertificatesManager.getInstance().apply {
//        putMerchant(
//            merchantId,
//            WechatPay2Credentials(
//                merchantId,
//                PrivateKeySigner(wechatProperties.pay.merchantCASerialNumber, privateKey)
//            ),
//            apiV3KeyByteArray
//        )
//    }.getVerifier(merchantId)
//    private val wechatPay2Validator = WechatPay2Validator(verifier)
//    private val httpClient = WechatPayHttpClientBuilder.create()
//        .withMerchant(merchantId, wechatProperties.pay.merchantCASerialNumber, privateKey)
//        .withValidator(wechatPay2Validator)
//        .addInterceptorFirst(HttpRequestInterceptor { request, _ ->
//            request.addHeader(HttpHeaders.ACCEPT, "application/json")
//            request.addHeader(HttpHeaders.CONTENT_TYPE, "application/json; charset=utf-8")
//        })
////        .withWechatPay(wechatPayCertificates)
//        .build()
//
//    private val notificationHandler = NotificationHandler(verifier, apiV3KeyByteArray)
//
//
//    /**
//     * https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_2_1.shtml
//     * @return prepay_id
//     */
//    private fun appPrePay(
//        appId: String,
//        description: String,
//        out_trade_no: String,
//        notify_url: String,
//        total: Int
//    ): String {
//        val prePayUrl = "https://api.mch.weixin.qq.com/v3/pay/transactions/app"
//        return this.prePay(prePayUrl, appId, description, out_trade_no, notify_url, total)
//    }
//
//    private fun jsapiPrePay(
//        appId: String,
//        description: String,
//        out_trade_no: String,
//        notify_url: String,
//        total: Int,
//        payerOpenId:String
//
//    ): String {
//        val prePayUrl = "https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi"
//        return this.prePay(prePayUrl, appId, description, out_trade_no, notify_url, total,payerOpenId)
//    }
//
//    private fun prePay(
//        prePayUrl: String, appId: String,
//        description: String,
//        out_trade_no: String,
//        notify_url: String,
//        total: Int,
//        payerOpenId: String? = null
//    ): String {
//        val httpPost = HttpPost(prePayUrl)
//        val bos = ByteArrayOutputStream()
//
//        val rootNode: ObjectNode = objectMapper.createObjectNode()
//        rootNode.put("mchid", merchantId)
//            .put("appid", appId)
//            .put("description", description)
//            .put("notify_url", notify_url)
//            .put("out_trade_no", out_trade_no)
//        rootNode.putObject("amount")
//            .put("total", total)
//        payerOpenId?.let{
//            rootNode.putObject("payer")
//                .put("openid", payerOpenId)
//        }
//
//        objectMapper.writeValue(bos, rootNode)
//
//        httpPost.entity = StringEntity(bos.toString("UTF-8"), "UTF-8")
//        val closeableHttpResponse = httpClient.execute(httpPost)
//
//        val responseJsonNode = objectMapper.readTree(closeableHttpResponse.entity.content)
//        if (log.isDebugEnabled) {
//            log.debug("closeable http content: {}", responseJsonNode.toPrettyString())
//        }
//        return responseJsonNode["prepay_id"].textValue()
//    }
//
//    fun appPrePayAndSign(
//        description: String,
//        out_trade_no: String,
//        notify_url: String,
//        total: Int
//    ): WechatPrepaySignData {
//        val appId = wechatProperties.app.appId
//        val prepayId = this.appPrePay(appId, description, out_trade_no, notify_url, total)
//        return generateAppPrepaySignData(appId, prepayId)
//    }
//
//    fun miniPrePayAndSign(
//        description: String,
//        out_trade_no: String,
//        notify_url: String,
//        total: Int,
//        payerOpenId: String
//    ): WechatPrepaySignData {
//        val appId = wechatProperties.mini.appId
//        val prepayId = this.jsapiPrePay(appId, description, out_trade_no, notify_url, total,payerOpenId)
//        return generateMiniPrepaySignData(appId, prepayId)
//    }
//
//    private fun generateAppPrepaySignData(
//        appId: String,
//        prepayId: String
//    ): WechatPrepaySignData {
//        val nonceStr = RandomStringUtils.randomAlphanumeric(32)
//        val timeStamp = (Date().time / 1000)
//        val stringToSign = "$appId\n$timeStamp\n$nonceStr\n$prepayId\n"
//        val signature = Signature.getInstance("SHA256withRSA")
//        signature.initSign(privateKey)
//        signature.update(stringToSign.toByteArray(StandardCharsets.UTF_8))
//        val sign = Base64.encodeBase64String(signature.sign())
//        return WechatPrepaySignData(prepayId, merchantId, appId, "Sign=WXPay", nonceStr, timeStamp, sign)
//    }
//
//    private fun generateMiniPrepaySignData(appId: String,
//                                           prepayId: String): WechatPrepaySignData {
//        val nonceStr = RandomStringUtils.randomAlphanumeric(32)
//        val timeStamp = (Date().time / 1000)
//        val `package` = "prepay_id=$prepayId"
//        val stringToSign = "$appId\n$timeStamp\n$nonceStr\n$`package`\n"
//        val signature = Signature.getInstance("SHA256withRSA")
//        signature.initSign(privateKey)
//        signature.update(stringToSign.toByteArray(StandardCharsets.UTF_8))
//        val sign = Base64.encodeBase64String(signature.sign())
//        return WechatPrepaySignData(prepayId, merchantId, appId, `package`, nonceStr, timeStamp, sign)
//    }
//
//    data class WechatPrepaySignData(
//        val prepayId: String,
//        val partnerId: String,
//        val appId: String,
//        val `package`: String,
//        val nonceStr: String,
//        val timeStamp: Long,
//        val sign: String
//    )
//
//
//
//    @Suppress("PropertyName")
//    class AppPayNotificationDecryptData(json: JsonNode) {
//        val appid: String by json
//        val mchid: String by json
//        val out_trade_no: String by json
//        private val success_time: String by json
//        val successDateTime: LocalDateTime
//            get() = LocalDateTime.parse(success_time, DateTimeFormatter.ISO_DATE_TIME)
//    }
//
//    class NotificationErrorResponse(
//        val code: Code,
//        val message: String
//    ) {
//        companion object {
//            fun fail(message: String): NotificationErrorResponse {
//                return NotificationErrorResponse(Code.FAIL, message)
//            }
//        }
//
//        enum class Code {
//            FAIL,
//        }
//    }
//
//
//}
//
//private operator fun JsonNode.getValue(appPayNotificationDecryptData: Any, property: KProperty<*>): String {
//    return this[property.name].textValue()
//}
//
//
